home *** CD-ROM | disk | FTP | other *** search
- /*
- This was written for 3.2; it may not work under 3.1, though I'd be
- (relatively) happy to have someone try it.
-
- Note that this could probably be more efficient if I could figure out
- how to directly search the TCP control blocks. Unfortunately, I have
- no idea where they're stored in the kernel, and I didn't really want to
- spend a lot of time figuring it out. With 20 users logged on and >100
- connections, it only takes about .1 second to identify a connection on
- this 530.
-
- Like authd, pauthd, and pidentd, aixident is meant to be started from
- inetd:
-
- ident stream tcp nowait root /usr/local/etc/aixident in.identd -l
-
- The name is pronounced like "accident", because that's what I believe
- RFC931 is. Use at your own risk.
- */
-
- /*
- ** aixident -- AIX identification daemon
- ** version 1.0
- **
- ** Copyright 1992 by Charles M. Hannum.
- **
- ** Permission is granted to copy, modify, and use this program in any way,
- ** so long as the above copyright notice, this permission notice, and the
- ** warranty disclaimer below remain on all copies, and are unaltered.
- **
- ** aixident is distributed in the hope that it will be useful, but WITHOUT
- ** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- ** FITNESS FOR A PARTICULAR PURPOSE.
- */
-
- /*
- ** Usage:
- **
- ** aixident [-l] [-V] [-v] [-d] [kmem_file]
- **
- ** Where:
- **
- ** -l log via syslog
- **
- ** -V print version number and exit
- **
- ** -v verbose (currently useless)
- **
- ** -d enable debugging; lists connections in a lsof-like manner
- **
- ** kmem_file file to read kernel memory from
- */
-
- char version[] = "aixident, version 1.0";
-
- #include <sys/types.h>
-
- #include <stdlib.h>
- #include <errno.h>
- #include <pwd.h>
- #include <stdio.h>
- #include <syslog.h>
-
- #include <sys/domain.h>
- #include <sys/protosw.h>
- #include <sys/socket.h>
- #include <sys/socketvar.h>
- #include <sys/vfs.h>
- #include <net/route.h>
- #include <netinet/in.h>
- #include <netinet/in_pcb.h>
- #include <arpa/inet.h>
-
- #define _KERNEL 1
- #include <sys/file.h>
- #undef _KERNEL
- #include <procinfo.h>
-
- int kmem;
-
- int kread ();
- char *printuid ();
- void printaddr ();
-
- int syslog_flag = 0,
- verbose_flag = 0,
- debug_flag = 0;
-
- #define ERROR(v,m) \
- do { \
- printf ("%d, %d: ERROR: %s\r\n", local_port, foreign_port, m); \
- exit (v); \
- } while (0)
-
- #define UNKNOWN_ERROR() ERROR (1, "UNKNOWN-ERROR");
-
- int
- main (argc, argv)
- int argc;
- char **argv;
- {
- char *path_kmem = "/dev/kmem";
- struct sockaddr_in foreign, local;
- int foreign_len, local_len;
- int foreign_port = 0, local_port = 0;
- int max_procs = 64,
- num_procs, fd;
- struct procinfo *procinfo;
- struct user user;
- struct file *filep, file;
- struct socket *socketp, socket;
- struct protosw *protoswp, protosw;
- struct domain *domainp, domain;
- struct inpcb *inpcbp, inpcb;
- struct passwd *passwd;
-
- for (--argc; argc && **++argv == '-'; argc--)
- while (*(++*argv))
- switch (**argv) {
- case 'l':
- syslog_flag = 1;
- break;
- case 'V':
- puts (version);
- exit (0);
- break;
- case 'v':
- verbose_flag = 1;
- break;
- case 'd':
- debug_flag = 1;
- break;
- }
-
- if (argc) {
- path_kmem = *(argv++);
- --argc;
- }
-
- foreign_len = sizeof (foreign);
- if (getpeername (0, &foreign, &foreign_len) == -1) {
- perror ("getpeername");
- exit (1);
- }
-
- local_len = sizeof (local);
- if (getsockname (0, &local, &local_len) == -1) {
- perror ("getsockname");
- exit (1);
- }
-
- if (syslog_flag) {
- (void) openlog ("identd", LOG_PID, LOG_DAEMON);
- (void) syslog (LOG_NOTICE, "Connection from %s",
- inet_ntoa (foreign.sin_addr.s_addr));
- }
-
- if (scanf ("%d , %d", &local_port, &foreign_port) != 2 ||
- local_port < 1 || local_port > 65535 || foreign_port < 1 ||
- foreign_port > 65535) {
- if (syslog_flag)
- (void) syslog (LOG_INFO, "invalid port(s): %d, %d", local_port,
- foreign_port);
- ERROR (0, "INVALID-PORT");
- }
-
- if ((kmem = open (path_kmem, O_RDONLY)) == -1) {
- if (syslog_flag)
- (void) syslog (LOG_ERR, "error opening /dev/kmem: %s", strerror (errno));
- UNKNOWN_ERROR ();
- }
-
- while ((procinfo = (struct procinfo *)
- malloc ((size_t) (max_procs * sizeof (*procinfo)))) &&
- (num_procs = getproc (procinfo, max_procs,
- sizeof (*procinfo))) == -1 &&
- errno == ENOSPC) {
- max_procs <<= 1;
- free (procinfo);
- }
-
- if (! procinfo) {
- if (syslog_flag)
- (void) syslog (LOG_ERR, "out of memory allocating %ld procinfo structs\n",
- max_procs);
- UNKNOWN_ERROR ();
- }
-
- for (; num_procs; num_procs--, procinfo++) {
-
- if (procinfo->pi_stat == 0 || procinfo->pi_stat == SZOMB)
- continue;
-
- if (getuser (procinfo, sizeof (*procinfo), &user, sizeof (user)))
- continue;
-
- for (fd = 0; fd < user.u_maxofile; fd++) {
-
- if (! (filep = user.u_ufd[fd].fp))
- continue;
-
- if (kread ((off_t) filep, (char *) &file, sizeof (file))) {
- if (syslog_flag)
- (void) syslog (LOG_ERR, "can't read file struct from %#x",
- (unsigned) filep);
- UNKNOWN_ERROR ();
- }
-
- if (file.f_type != DTYPE_SOCKET)
- continue;
-
- if (! (socketp = (struct socket *) file.f_data))
- continue;
-
- if (kread ((off_t) socketp, (char *) &socket, sizeof (socket))) {
- if (syslog_flag)
- (void) syslog (LOG_ERR, "can't read socket struct from %#x",
- (unsigned) socketp);
- UNKNOWN_ERROR ();
- }
-
- if (! (protoswp = socket.so_proto))
- continue;
-
- if (kread ((off_t) protoswp, (char *) &protosw, sizeof (protosw))) {
- if (syslog_flag)
- (void) syslog (LOG_ERR, "can't read protosw struct from %#x",
- (unsigned) protoswp);
- UNKNOWN_ERROR ();
- }
-
- if (protosw.pr_protocol != IPPROTO_TCP)
- continue;
-
- if (! (domainp = protosw.pr_domain))
- continue;
-
- if (kread ((off_t) domainp, (char *) &domain, sizeof (domain))) {
- if (syslog_flag)
- (void) syslog (LOG_ERR, "can't read domain struct from %#x",
- (unsigned) domainp);
- UNKNOWN_ERROR ();
- }
-
- if (domain.dom_family != AF_INET)
- continue;
-
- if (! (inpcbp = (struct inpcb *) socket.so_pcb))
- continue;
-
- if (kread ((off_t) inpcbp, (char *) &inpcb, sizeof (inpcb))) {
- if (syslog_flag)
- (void) syslog (LOG_ERR, "can't read inpcb struct from %#x",
- (unsigned) inpcbp);
- UNKNOWN_ERROR ();
- }
-
- if (socketp != inpcb.inp_socket)
- continue;
-
- if (inpcb.inp_faddr.s_addr != foreign.sin_addr.s_addr ||
- inpcb.inp_fport != foreign_port ||
- inpcb.inp_laddr.s_addr != local.sin_addr.s_addr ||
- inpcb.inp_lport != local_port)
- continue;
-
- if (! (passwd = getpwuid (procinfo->pi_uid))) {
- if (syslog_flag)
- (void) syslog (LOG_WARNING, "could not map uid to name: %d",
- procinfo->pi_uid);
- UNKNOWN_ERROR ();
- }
-
- if (!debug_flag) {
- if (syslog_flag)
- (void) syslog (LOG_NOTICE, "identified: %d, %d, %s", local_port,
- foreign_port, passwd->pw_name);
- printf ("%d, %d: USERID: UNIX: %s\r\n", local_port, foreign_port,
- passwd->pw_name);
- exit (0);
- } else {
- printf ("%-9.9s%6d %8s %4d%c %4.4s 0x%08x %8s %7.7s ",
- user.u_comm, procinfo->pi_pid, printuid (procinfo->pi_uid),
- fd, ' ', "inet", inpcb.inp_ppcb ?
- (int) inpcb.inp_ppcb : (int) socket.so_pcb,
- "", "TCP");
-
- printaddr (&inpcb.inp_laddr, inpcb.inp_lport);
- if (inpcb.inp_faddr.s_addr != INADDR_ANY || inpcb.inp_fport) {
- printf ("->");
- printaddr (&inpcb.inp_faddr, inpcb.inp_fport);
- }
-
- printf ("\n");
- }
- }
- }
-
- if (syslog_flag)
- (void) syslog (LOG_DEBUG, "not found: %d, %d", local_port, foreign_port);
- ERROR (0, "NO-USER");
- }
-
- int
- kread (addr, buf, len)
- off_t addr;
- char *buf;
- int len;
- {
- int br;
-
- if (lseek (kmem, addr, L_SET) == (off_t) -1)
- return (-1);
-
- br = read(kmem, buf, len);
-
- return ((br == len) ? 0 : 1);
- }
-
- char *
- printuid (uid)
- uid_t uid;
- {
- static int used = 0;
- static uid_t last_uid;
- struct passwd *passwd;
- static char user[9];
-
- if (!used || uid != last_uid) {
- used = 1;
- last_uid = uid;
-
- if (passwd = getpwuid (uid))
- (void) strcpy (user, passwd->pw_name);
- else
- (void) sprintf (user, "%d", uid);
- }
-
- return (user);
- }
-
- void
- printaddr (in_addr, port)
- struct in_addr *in_addr;
- u_short port;
- {
- if (in_addr->s_addr == INADDR_ANY)
- printf ("*:%d", port);
- else
- printf ("%s:%d", inet_ntoa (in_addr->s_addr), port);
- }
-
-